package com.pine.app.module.security.oauth.plugin;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author xiaoyuan
 * @create 2020/3/6 22:38
 **/
public class DefaultProcessPluginChain implements ProcessPluginChain {

    private List<ProcessPlugin> observerList = new ArrayList<>();

    @Override
    public void attach(ProcessPlugin observer) {
        observerList.add(observer);
        observerList.sort(Comparator.comparing(ProcessPlugin::getOrder));
    }

    @Override
    public void detach(ProcessPlugin observer) {
        observerList.remove(observer);
        observerList.sort(Comparator.comparing(ProcessPlugin::getOrder));
    }

    @Override
    public void attachAll(List<ProcessPlugin> list) {
        observerList.addAll(list);
        observerList.sort(Comparator.comparing(ProcessPlugin::getOrder));
    }

    @Override
    public void prepare(HttpServletRequest request, HttpServletResponse response, Object o, Plugin plugin) {
        List<ProcessPlugin> list = observerList.stream().filter(ob -> ob.matcher(request, plugin)).collect(Collectors.toList());
        list.forEach(observer -> {
            if (observer.matcher(request, plugin)) {
                observer.setEnabled(false);
                try {
                    observer.prepare(request, response, o);
                } catch (ServletException e) {
                    throw new RuntimeException(e.getMessage());
                } catch (IOException e) {
                    throw new RuntimeException(e.getMessage());
                }
                observer.setEnabled(true);
            }
        });
    }

    @Override
    public void complete(HttpServletRequest request, HttpServletResponse response, Object o, Plugin plugin) {
        List<ProcessPlugin> list = observerList.stream().filter(ob -> ob.matcher(request, plugin)).collect(Collectors.toList());
        list.forEach(observer -> {
            if (observer.matcher(request, plugin)) {
                observer.complete(request, response, o);
            }
        });
    }

    @Override
    public void exception(HttpServletRequest request, HttpServletResponse response, Exception e, Plugin plugin) {
        List<ProcessPlugin> list = observerList.stream().filter(ob -> ob.matcher(request, plugin)).collect(Collectors.toList());
        list.forEach(observer -> {
            if (observer.matcher(request, plugin)) {
                try {
                    observer.exception(request, response, e);
                } catch (ServletException ex) {
                    throw new RuntimeException(e.getMessage());
                } catch (IOException ex) {
                    throw new RuntimeException(e.getMessage());
                }
            }
        });
    }

}
